{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`std::atomic<T>` 是 C++11 引入的原子类型包装器。它提供对基础类型 `T` 的**不可分割读写和读-改-写操作**，从而在多线程环境中消除数据竞争（data race）。\n",
    "\n",
    "- **原子性**：一次操作要么全部完成，要么完全不生效，不会出现中间状态。\n",
    "- **可见性与顺序性**：通过**内存序(memory order)**约束编译器与 CPU 的指令重排，控制数据在不同线程之间传播的时机和顺序。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 常见成员函数\n",
    "\n",
    "| 成员类别        | 函数                                                    | 说明                                                    |\n",
    "| --------------- | ------------------------------------------------------- | ------------------------------------------------------- |\n",
    "| 读写            | `load()` / `store()`                                    | 原子读 / 写                                             |\n",
    "| 读-改-写（RMW） | `fetch_add()` / `fetch_sub()` / `fetch_or()` 等         | 原子读取旧值并写入新值                                  |\n",
    "| 比较交换        | `compare_exchange_strong()` / `compare_exchange_weak()` | CAS：仅当当前值与期望值相等时才写入新值，并返回比较结果 |\n",
    "\n",
    "这些成员函数都可以带可选的 `std::memory_order` 参数，用于指定内存序。默认是 `std::memory_order_seq_cst`（顺序一致性），最安全但可能因序列化而牺牲性能。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 内存序（memory order）选择指南\n",
    "\n",
    "| 存序                                            | 保障                                                         | 典型用途                                                |\n",
    "| ----------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------- |\n",
    "| `memory_order_relaxed`                          | 仅保证原子性，不保证可见性或排序                             | 统计计数器、无需同步其他数据的场景                      |\n",
    "| `memory_order_acquire` / `memory_order_release` | Acquire 保证后续读写不被重排到原子操作之前；Release 保证之前的写不被重排到原子操作之后 | 配合使用实现“先写数据，再置标志”的模式（生产者-消费者） |\n",
    "| `memory_order_acq_rel`                          | 同时具备 Acquire 与 Release 语义                             | 常用于读-改-写类操作                                    |\n",
    "| `memory_order_seq_cst`                          | 最强保证：所有线程观察到相同的全局顺序                       | 首选的默认选项，除非需要极致性能                        |"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "// 写线程：先生产数据，再发布标志\n",
    "data = new_value;\n",
    "flag.store(true, std::memory_order_release);\n",
    "\n",
    "// 读线程：先观察标志，再消费数据\n",
    "if (flag.load(std::memory_order_acquire)) {\n",
    "    consume(data);\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## CAS（Compare-And-Swap，比较并交换）"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "| 概念       | 说明                                                         |\n",
    "| ---------- | ------------------------------------------------------------ |\n",
    "| 核心思路   | 比较某个内存位置的当前值是否与期望值一致，若一致则写入新值并返回成功；否则不写入并返回失败。 |\n",
    "| 原子性保障 | 在硬件层面保证比较与写入的不可分割性，避免竞态条件。         |\n",
    "| 使用场景   | 无锁数据结构（如无锁队列、无锁栈）、状态机推进、原子引用计数、一次性初始化（compare-and-swap 双检锁）等。 |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- CAS 函数原型（以 C++ `std::atomic` 为例）\n",
    "\n",
    "| 函数形式                                               | 说明                                                         |\n",
    "| ------------------------------------------------------ | ------------------------------------------------------------ |\n",
    "| `bool compare_exchange_strong(T& expected, T desired)` | 精确比较，若值不等返回失败，`expected` 被更新为当前值。适合成功率高的场景，失败时不会伪失败。 |\n",
    "| `bool compare_exchange_weak(T& expected, T desired)`   | 可能产生伪失败（即使当前值相等，也可能返回失败），适合在循环中使用并允许硬件优化。 |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- CAS 成功 / 失败路径\n",
    "\n",
    "| 步骤            | 成功路径                           | 失败路径                                       |\n",
    "| --------------- | ---------------------------------- | ---------------------------------------------- |\n",
    "| 1. 读取当前值   | 获取原子变量当前值，存入 `current` | 同左                                           |\n",
    "| 2. 比较与期望值 | `current == expected`              | `current != expected` 或伪失败                 |\n",
    "| 3. 写入操作     | 原子写入 `desired`，返回 true      | 不写入；将 `expected` 更新为实际值，返回 false |\n",
    "| 4. 调用者处理   | 进入下一阶段逻辑                   | 更新期望值并重试或放弃操作                     |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "CAS 常见使用模式\n",
    "\n",
    "| 模式            | 代码要点                                                    | 示例场景                        |\n",
    "| --------------- | ----------------------------------------------------------- | ------------------------------- |\n",
    "| 自旋重试        | 在 `while (!cas) { /* 更新 expected */ }` 中循环直到成功    | 无锁栈 push/pop、原子更新最大值 |\n",
    "| 有限重试 + 回退 | 避免无限自旋，重试一定次数后退避或降级为锁                  | 高争用热点，保护系统吞吐        |\n",
    "| 检测状态变化    | 借助 CAS 保证状态由 `STATE::Init → STATE::Ready` 仅发生一次 | 单例初始化、安全状态推进        |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 内存序（Memory Order）详解"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`std::atomic` 的每次操作都可以指定内存序（memory order），用来描述该操作在不同线程之间的可见性与重排约束。理解这些序非常关键，因为它直接决定跨线程更新的同步语义、性能与正确性。\n",
    "\n",
    "| 内存序                 | 语义特点                                                     | 使用场景                                                     | 详细说明                                                     |\n",
    "| ---------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |\n",
    "| `memory_order_seq_cst` | 全局单调顺序，编译器与 CPU 均不得重排；所有线程观察到一致的执行顺序。 | 调试阶段、业务对时序极敏感、需要线性化语义。                 | 默认值，最安全但性能可能稍低。适合不熟悉内存序或必须保证“看起来像单线程执行”时使用。 |\n",
    "| `memory_order_acquire` | 读操作屏障：阻止其后的读写越过该点。                         | 与 `release` 搭配实现生产者/消费者、状态同步。               | 读取原子变量后，可安全访问由 `release` 发布的数据。常用于“等待某标志再访问共享数据”的场景。 |\n",
    "| `memory_order_release` | 写操作屏障：阻止其前的读写越过该点。                         | 发布共享状态、通知其他线程。                                 | 在发布标志前对共享数据进行更新，确保读取到标志的线程也能看到对应的数据。与 `acquire` 配对形成“写锁/读锁”语义。 |\n",
    "| `memory_order_acq_rel` | 同时具备 acquire 与 release 语义。                           | 原子读-改-写（RMW）操作，如 `fetch_add`、CAS 成功路径等，需要同步读写双方。 | 既能读取其他线程发布的数据，又能将自己的修改发布给后续读者。典型场景：引用计数、计数器递增。 |\n",
    "| `memory_order_relaxed` | 仅保证原子性，不提供可见性或顺序约束。                       | 单纯统计、无外部数据依赖的场景（命中计数等）。               | 不能依赖它来传播其他非原子数据。只关心最终数值或相对值时使用，可显著提升性能。 |\n",
    "| `memory_order_consume` | 理论上为数据依赖同步；实际实现通常退化为 `acquire`。         | 几乎不推荐使用，标准拟弱化/移除。                            | 由于实现差异和推理困难，请直接使用 `acquire` 代替。          |\n",
    "\n",
    "> **重点提示：** `seq_cst` 最安全但性能一般，`acquire/release` 提供可控同步，`relaxed` 只保证原子性。实际工程中，可先使用 `seq_cst` 保证正确性，再在性能敏感区域逐步替换为更细粒度的内存序。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Acquire/Release 配合示意\n",
    "\n",
    "| 线程   | 操作               | 内存序                 | 保证                                             |\n",
    "| ------ | ------------------ | ---------------------- | ------------------------------------------------ |\n",
    "| 生产者 | 写入数据结构       | 普通写                 | -                                                |\n",
    "| 生产者 | `flag.store(true)` | `memory_order_release` | 确保之前写入的数据对后续 Acquire 访问者可见      |\n",
    "| 消费者 | `flag.load()`      | `memory_order_acquire` | 确保读取到 `true` 后，能看到生产者已经写入的数据 |\n",
    "| 消费者 | 读取数据结构       | 普通读                 | 通过 Acquire 保障读取顺序正确                    |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## CAS 与内存序"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- CAS 与内存序的组合策略\n",
    "\n",
    "| 操作类型                        | 推荐内存序                                                | 理由                                               |\n",
    "| ------------------------------- | --------------------------------------------------------- | -------------------------------------------------- |\n",
    "| `compare_exchange_xxx` 成功路径 | `memory_order_acq_rel`                                    | 成功时既要发布此前写入，又要获取后续读取的最新状态 |\n",
    "| `compare_exchange_xxx` 失败路径 | 一般使用 `memory_order_relaxed` 或 `memory_order_acquire` | 失败时无需发布写入，可视情况读取最新值             |\n",
    "| 纯读取（无写入）                | `memory_order_acquire` 或 `seq_cst`                       | 确保读到最新可见状态                               |\n",
    "| 纯写入（发布数据）              | `memory_order_release` 或 `seq_cst`                       | 确保数据在写标志位前可见                           |\n",
    "| 松散计数器                      | `memory_order_relaxed`                                    | 不依赖顺序，仅需原子性                             |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- CAS 与内存序协作的常见案例\n",
    "\n",
    "| 案例           | 内存序配置                                                   | 说明                             |\n",
    "| -------------- | ------------------------------------------------------------ | -------------------------------- |\n",
    "| 无锁栈 push    | `compare_exchange_weak(head, new_node, std::memory_order_release, std::memory_order_relaxed)` | 发布新节点，失败回退只需 relaxed |\n",
    "| 无锁栈 pop     | `compare_exchange_weak(head, next, std::memory_order_acquire, std::memory_order_relaxed)` | 获取旧节点内容，失败回退 relaxed |\n",
    "| 单例初始化     | 成功写入使用 `memory_order_release`，读取使用 `memory_order_acquire` | 确保构造完成后其他线程可见       |\n",
    "| 原子引用计数   | `fetch_add` 使用 `relaxed`，`fetch_sub` 使用 `acq_rel`，归零后 Delete 前再执行一次 `acquire` | 删除前确保其他线程操作已完成     |\n",
    "| 状态机关联数据 | 状态原子变量使用 `compare_exchange_strong` 搭配 `acq_rel`    | 保证状态切换伴随数据可见性更新   |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- CAS 与内存序的常见陷阱与规避策略\n",
    "\n",
    "| 问题场景         | 具体表现                                  | 规避建议                                                     |\n",
    "| ---------------- | ----------------------------------------- | ------------------------------------------------------------ |\n",
    "| ABA 问题         | 值从 A → B → A，CAS 检测不到变化          | 使用带版本号的指针、Hazard Pointer、`std::atomic<std::shared_ptr>` |\n",
    "| 忙等开销大       | 高争用下频繁自旋导致 CPU 飙升             | 引入退避策略、结合 `std::this_thread::yield()` 或 `std::this_thread::sleep_for` |\n",
    "| 内存序过于宽松   | 使用 `relaxed` 导致其他线程看不到最新数据 | 明确数据依赖，必要时使用 Acquire/Release 或 `seq_cst`        |\n",
    "| 伪共享           | 多个原子变量共享同一缓存行，相互干扰      | 使用 `alignas(64)` 或缓存行填充结构体                        |\n",
    "| 可见性与顺序混淆 | 只有原子性保证，仍出现逻辑错误            | 画出“写入 → 发布 → 观察”的时间线，逐条确认内存序             |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 实战建议总结\n",
    "\n",
    "1. **先安全、后优化**：默认使用 `memory_order_seq_cst`，确认性能瓶颈后再替换为更细的内存序。\n",
    "2. **CAS 必须配循环**：`compare_exchange_weak` 需要在循环内重试；`compare_exchange_strong` 可减少伪失败但仍建议循环。\n",
    "3. **Acquire/Release 配对出现**：写入数据（Release）→ 写入标志；读取标志（Acquire）→ 读取数据。\n",
    "4. **清晰的状态管理**：对状态原子变量使用 CAS，更易表达“仅在当前状态满足条件时才推进”的逻辑。\n",
    "5. **结合测试工具**：使用 ThreadSanitizer、Helgrind 等工具辅助发现数据竞争和内存序问题。\n",
    "\n",
    "通过正确使用 CAS 及合理选择内存序，可以构建高性能、多线程安全的无锁组件。但同时要警惕易错细节，保持代码可读性与可维护性。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 业务场景示例"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 演示基于 std::atomic 的高频计数器: [atomic_counter_example.cpp](./atomic_counter_example.cpp)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "=== Atomic Counter Example ===\n",
      "Expected: 400000, Actual: 400000\n"
     ]
    }
   ],
   "source": [
    "! g++ -std=c++17 -pthread atomic_counter_example.cpp -o atomic_counter_example && ./atomic_counter_example"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 使用 CAS（比较交换）构建的简单无锁栈: [lock_free_stack_example.cpp](./lock_free_stack_example.cpp)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "=== Lock-Free Stack Example ===\n",
      "Total pushed: 10000, Total popped: 10000\n"
     ]
    }
   ],
   "source": [
    "! g++ -std=c++17 -pthread lock_free_stack_example.cpp -o lock_free_stack_example && ./lock_free_stack_example"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 简易的引用计数基类: [refcount_example.cpp](./refcount_example.cpp)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "=== Atomic Reference Counting Example ===\n",
      "SharedResource working on thread 135016805824064\n",
      "SharedResource working on thread 135016797431360\n",
      "SharedResource working on thread 135016789038656\n",
      "SharedResource working on thread 135016780645952\n",
      "SharedResource destroyed\n"
     ]
    }
   ],
   "source": [
    "! g++ -std=c++17 -pthread refcount_example.cpp -o refcount_example && ./refcount_example"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 使用 `std::atomic<bool>` 管理服务状态的示例类: [service_flag_example.cpp](./service_flag_example.cpp)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "=== Atomic Flag Example ===\n",
      "Thread Thread 138001294292544 started the service\n",
      "138001285899840 found service already running\n",
      "Service running? true\n",
      "Service stopped successfully\n",
      "Service was already stopped\n"
     ]
    }
   ],
   "source": [
    "! g++ -std=c++17 -pthread service_flag_example.cpp -o service_flag_example && ./service_flag_example"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- 固定容量的单生产者单消费者环形缓冲区: [ring_buffer_example.cpp](./ring_buffer_example.cpp)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "=== Atomic Ring Buffer Example ===\n",
      "Consumer got value: 0\n",
      "Consumer got value: 1\n",
      "Consumer got value: 2\n",
      "Consumer got value: 3\n",
      "Consumer got value: 4\n",
      "Consumer got value: 5\n",
      "Consumer got value: 6\n",
      "Consumer got value: 7\n",
      "Consumer got value: 8\n",
      "Consumer got value: 9\n",
      "Consumer got value: 10\n",
      "Consumer got value: 11\n",
      "Consumer got value: 12\n",
      "Consumer got value: 13\n",
      "Consumer got value: 14\n",
      "Consumer got value: 15\n",
      "Consumer got value: 16\n",
      "Consumer got value: 17\n",
      "Consumer got value: 18\n",
      "Consumer got value: 19\n",
      "Consumer total count: 20\n"
     ]
    }
   ],
   "source": [
    "! g++ -std=c++17 -pthread ring_buffer_example.cpp -o ring_buffer_example && ./ring_buffer_example"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "vscode": {
     "languageId": "shellscript"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "=== SpinLock Example ===\n",
      "Counter guarded by SpinLock: 400000\n"
     ]
    }
   ],
   "source": [
    "! g++ -std=c++17 -pthread spin_lock_example.cpp -o spin_lock_example && ./spin_lock_example"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 使用注意事项总结\n",
    "\n",
    "1. **内存序选择**：`seq_cst` 最安全，若需优化性能，可针对具体数据流设计合适的 Acquire/Release 或 Relaxed 操作。注意：Relaxed 只保证原子性，不保证可见性。\n",
    "2. **成对使用 Acquire/Release**：常见模式是写线程用 Release 发布，读线程用 Acquire 获取，确保数据正确传播。\n",
    "3. **避免 ABA 问题**：CAS 指针操作会遭遇 ABA，常用解决方案是：\n",
    "   - 使用带版本号的指针（即打包指针与计数）。\n",
    "   - 利用 `std::atomic<std::shared_ptr>`。\n",
    "   - 引入 Hazard Pointer 等更复杂的安全机制。\n",
    "4. **类型限制**：`std::atomic` 仅支持 trivially copyable 类型。如果类型过于复杂，可采用 `std::atomic<std::shared_ptr<T>>` 或将共享数据封装为指针。\n",
    "5. **自旋等待策略**：自旋适用于临界区极短的场景。可在循环中加入 `std::this_thread::yield()`、`_mm_pause()` 或退避策略，降低 CPU 占用。\n",
    "6. **对齐与 False Sharing**：多个频繁更新的原子变量共享同一缓存行会导致缓存抖动。可用 `alignas(CacheLineSize)` 或填充结构体避免伪共享。\n",
    "7. **调试与测试难度大**：弱一致性、平台差异导致问题难以复现。建议使用 ThreadSanitizer 等工具，并在不同 CPU、编译器优化级别下验证。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 潜在缺陷 / 局限\n",
    "\n",
    "- **推理复杂**：正确选择内存序并证明正确性较难，错误往往难以定位。\n",
    "- **忙等开销**：在高争用环境下，自旋或频繁 CAS 会导致 CPU 浪费。\n",
    "- **功能受限**：原子操作无法替代所有同步需求，复杂事务仍需锁、条件变量或其他高级原语。\n",
    "- **只保证原子性，不保证逻辑正确**：业务层面的竞态（例如跨多个字段的状态一致性）仍需额外同步。\n",
    "- **硬件差异**：不同架构的内存模型不同，错误的内存序在某些平台上或许表现正常，但在其它架构上失败。\n",
    "- **缺乏阻塞等待机制**：原子变量自身不会阻塞等待状态变化，如需阻塞需结合 `std::condition_variable` 或 `std::atomic_wait`（C++20）。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 实战建议清单\n",
    "\n",
    "- **默认优先使用 `std::memory_order_seq_cst`，确认性能瓶颈后再优化。**\n",
    "- **为每个原子操作绘制“写入–可见–读取”链路**，明确需要同步的对象和时机。\n",
    "- **对多字段场景，可考虑结构体一次性 load/store 或使用互斥锁。**\n",
    "- **在代码评审中重点检查 CAS 循环逻辑、内存序对是否符合预期。**\n",
    "- **引入单元测试和压力测试，结合动态分析工具（TSan）做跨平台验证。**"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C++17",
   "language": "C++17",
   "name": "xcpp17"
  },
  "language_info": {
   "codemirror_mode": "text/x-c++src",
   "file_extension": ".cpp",
   "mimetype": "text/x-c++src",
   "name": "c++",
   "version": "17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
